using System;
using System.Configuration;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;

namespace Common.Utilities
{
    /// <summary>
    /// 
    /// </summary>
    public static class ExceptionHandler
    {
        private static System.Diagnostics.EventLog Logger;

        static ExceptionHandler()
        {
            if (Logger == null)
            {
                try
                {
                    string logName = ConfigurationManager.AppSettings.Get("EventLogName");
                    string logSource = ConfigurationManager.AppSettings.Get("EventLogSource");
                    if (!EventLog.SourceExists(logSource))
                    {
                        EventLog.CreateEventSource(logSource, logName);
                    }
                    Logger = new EventLog(logName, ".", logSource);
                    Logger.MaximumKilobytes = 4096;
                    Logger.ModifyOverflowPolicy(OverflowAction.OverwriteAsNeeded, 7);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="ex"></param>
        public static void HandlesException(Exception ex)
        {
            if (Logger == null)
            {
                try
                {
                    string eventLogName = ConfigurationManager.AppSettings.Get("EventLogName");
                    string eventSrc = ConfigurationManager.AppSettings.Get("EventLogSource");
                    if ((!string.IsNullOrEmpty(eventLogName)) && (!string.IsNullOrEmpty(eventSrc)))
                    {
                        if(!EventLog.SourceExists(eventSrc))
                        {
                            EventLog.CreateEventSource(eventSrc, eventLogName);
                            Logger = new EventLog();
                            Logger.Log = eventLogName;
                            Logger.Source = eventSrc;
                            Logger.MaximumKilobytes = 4096;
                            Logger.ModifyOverflowPolicy(OverflowAction.OverwriteAsNeeded, 7);
                        }
                        else
                        {
                            Logger = new EventLog();
                            Logger.Log = eventLogName;
                            Logger.Source = eventSrc;    
                        }
                    }
                }
                catch(Exception ex2)
                {
                    Console.WriteLine(ex2.ToString());
                }
            }

            if (Logger != null)
            {
                
                string[] messages = TrimMessage(ex.Message);
                if(messages !=null && messages.Length>0)
                {
                    foreach(string msg in messages)
                    {
                        Logger.WriteEntry(msg, EventLogEntryType.Error);        
                    }
                }
                string[] errors = TrimMessage(ex.ToString());
                if(errors !=null && errors.Length>0)
                {
                    foreach(string error in errors)
                    {
                        Logger.WriteEntry(error, EventLogEntryType.Error);        
                    }
                }

                string[] traces = TrimMessage(ex.StackTrace);
                if(traces !=null && traces.Length>0)
                {
                    foreach(string trace in traces)
                    {
                        Logger.WriteEntry(trace, EventLogEntryType.Error);
                    }
                }
            }
            else
            {
                throw ex;    
            }
        }

        private static string[] TrimMessage(string msg)
        {
            if(!string.IsNullOrEmpty(msg))
            {
                List<string> errors=new List<string>();
                int pos = 0;
                while(pos<msg.Length)
                {
                    int len = Math.Min(1000, msg.Length - pos);
                    string error = msg.Substring(pos, len);
                    errors.Add(error);
                    pos = pos + len;
                }
                return errors.ToArray();
            }
            else
            {
                return new string[] {"Unknown error"};
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <param name="ex"></param>
        public static void HandlesException(Dispatcher.InstructionBase request, Exception ex)
        {
            if (Logger == null)
            {
                try
                {
                    string eventLogName = ConfigurationManager.AppSettings.Get("EventLogName");
                    string eventSrc = ConfigurationManager.AppSettings.Get("EventLogSource");
                    if ((!string.IsNullOrEmpty(eventLogName)) && (!string.IsNullOrEmpty(eventSrc)))
                    {
                        EventLog.CreateEventSource(eventSrc, eventLogName);
                    }
                    Logger = new EventLog();
                    Logger.Log = eventLogName;
                    Logger.Source = eventSrc;
                    Logger.MaximumKilobytes = 4096;
                    Logger.ModifyOverflowPolicy(OverflowAction.OverwriteAsNeeded, 7);
                }
                catch (Exception ex1)
                {
                    Trace.WriteLine(ex1.ToString());
                }
            }

            if(Logger !=null)
            {
                Logger.WriteEntry(request.GetType().ToString() + " has error", EventLogEntryType.Error);

                string[] messages = TrimMessage(ex.Message);
                if (messages != null && messages.Length > 0)
                {
                    foreach (string msg in messages)
                    {
                        Logger.WriteEntry(msg, EventLogEntryType.Error);
                    }
                }
                string[] errors = TrimMessage(ex.ToString());
                if (errors != null && errors.Length > 0)
                {
                    foreach (string error in errors)
                    {
                        Logger.WriteEntry(error, EventLogEntryType.Error);
                    }
                }
                string[] traces = TrimMessage(ex.StackTrace);
                if (traces != null && traces.Length > 0)
                {
                    foreach (string trace in traces)
                    {
                        Logger.WriteEntry(trace, EventLogEntryType.Error);
                    }
                }
            }
            else
            {
                throw new Exception(request.GetType().ToString() + " has error: " + TrimMessage(ex.ToString()));    
            }
        }
    }
}
